<?php
class BaseModelCache extends BaseModelMemCached implements BaseModelCacheMessage {
	const REALEXPIRE  = 15;
	const PREVEXPIRE  = 15;
	const REALPREFIX  = 'mc_realexpiretime';
	const KEYCONNECT  = '_';
	const HOSTSEPTOR  = ' ';
	const UDFMCPREFIX = 'mc_'; //compatible old mc version.
	private $_syncStat = FALSE;
	protected $keyPrefix = NULL;
	protected $cacheHost = NULL;
	
	public function __construct($prefix=NULL,$host=NULL) {
		defined('SKIPCACHE') || define('SKIPCACHE',2);//cache delete or cache insert action result not action status
		
		$this->keyPrefix = ($prefix ? $prefix : MC_KEY_PREFIX).self::UDFMCPREFIX;
		$this->cacheHost = $host   ? $host: IDCMC_SERVERS;
		$_svr = explode(self::HOSTSEPTOR,$this->cacheHost);
		$_main_svr = $_svr[0] ? $_svr[0] : '';
		$_rest_svr = array_shift($_svr);
		parent::__construct($_main_svr,$_svr);
	}
	public function getKeyPrefix() {
		return $this->keyPrefix;
	}
	public function getCacheHost() {
		return $this->cacheHost;
	}	
	/**
	* @describle get key name
	* @return string eg:club_edu_user_11230
	*/
	public function getKeyName() {
		$args = func_get_args();
		return $this->keyPrefix.implode(self::KEYCONNECT,$args);
	}
	private function _getRealKeyName() {
		$args = func_get_args();
		return $this->keyPrefix.implode(self::KEYCONNECT,$args);
	}
	public function setReal($key,$data)	{
		return $this->add($this->_getRealKeyName(self::REALPREFIX,$key),$data,self::REALEXPIRE);
	}
	public static function setMark($data) {
		return array_merge($data,array(self::REALPREFIX=>time()));
	}
	public static function isPreUpdate($data, $expire) {
		return ($data[self::REALPREFIX] + $expire - self::PREVEXPIRE) <= time();
	}
	public function setSyncStatus($syncStat) {
		$this->_syncStat = is_bool($syncStat) ? $syncStat : FALSE;
	}	
	public function getSyncStatus()	{
		return $this->_syncStat;
	}
	public function getSyncAction()	{
		return array('I','U','D');
	}
	public function syncMessage($uniqueKeyId,$action,$time,$data=NULL) {
		if( TRUE !== $this->getSyncStatus() ) {
			return FALSE;
		}
		$_this = new BaseModelCache(NULL,IDCMC_MSG_CENTER);
		$_key  = $uniqueKeyId;
		$_keyInc .= '_inc';
		
		defined('MCM_INCREMENT_STEP') || define('MCM_INCREMENT_STEP',1);
		defined('MCM_INC_EXPIRE') || define('MCM_INC_EXPIRE',600);
		defined('MCM_DATA_EXPIRE') || define('MCM_DATA_EXPIRE',300);
		
		$_inc  = $_this->add($_keyInc,MCM_INCREMENT_STEP,MCM_INC_EXPIRE);
		if( FALSE === $_inc ) {
			$_inc = $_this->increment($_keyInc);
		}
		else {
			$_inc = MCM_INCREMENT_STEP;
		}
		$action = strtoupper($action);
		if( !in_array($action,$_this->getSyncAction()) ) {
			trigger_error('Undefined Cache Action'.$action,E_USER_ERROR);
			return FALSE;
		} 
		$data  = array(
				'action' => $action,
				'time'   => $time,
				'data'   => $data
		);
		$_keyFinal .= $_inc;
		return $_this->add($_keyFinal,$data,$expireTime=MCM_DATA_EXPIRE);
	}
	public function mergeSyncData($uniqueKeyId,&$data) {
		$_keyInc = $uniqueKeyId.'_inc';
		$_this = new BaseModelCache(NULL,IDCMC_MSG_CENTER);
		$_ndata = $_this->get($_keyInc);
		if( FALSE === $_ndata ) {//no inc keys,meanning no concurrence occured between IDCs.
			return TRUE;
		}
		$_keyLast = $uniqueKeyId.$_ndata;
		$_data    = $_this->get($_keyLast);
		if( FALSE === $_data ) {//no key_0 value
			return TRUE;
		} 
		if( $_data['time'] < $data[REALPREFIX] ) {//the IDC is updated
			return TRUE;
		}
		if( $_data['action'] == 'D' ) {
			unset($data);
		}
		else if( $_data['data'] ) {
			$data = $_data;
		}
		return TRUE;
	}
}
?>